// Copyright 2007 Helsinki Institute for Information Technology
// and the authors.
//
// Authors: Harri Hämäläinen <harri.hamalainen@helsinki.fi>
//          Toni Ruottu <toni.ruottu@iki.fi>

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

function TrackerConnector() {
    var self = this;
    var currentcollection = null;
    var torrentdata = null;
    var torrentfiles = null;
    var torrentinfos = null;
    var peers = null;
    var TAG_MAX_LENGTH = 20;


    this.updateTorrentData = function(collection, reload) {
        var mustReload = false;
        if (reload || collection != currentcollection) {
            mustReload = true;
        }
        
        if (mustReload || torrentfiles == null || torrentinfos == null) {
            this.torrentdata = HttpConnector.doGet('/collection/'+collection+'/island/?output=json');
            this.torrentdata = this.torrentdata.evalJSON().data;
            this.torrentfiles = new Array();
            this.torrentinfos = new Array();
            for (var i=0; i<this.torrentdata.length; i++) {
                if (this.torrentdata[i][0].slice(41, 45) == 'file') {
                    this.torrentfiles.push(this.torrentdata[i]);
                } else if (this.torrentdata[i][0].slice(41, 45) == 'info') {
                    this.torrentinfos.push(this.torrentdata[i]);
                }
            }
            currentcollection = collection;
        }
    }

    this.getTorrentfiles = function(collection, reload) {
        this.updateTorrentData(collection, reload);
        return this.torrentfiles;
    }

    this.getTorrentinfos = function(collection,reload) {
        this.updateTorrentData(collection, reload);
        return this.torrentinfos;
    }

    this.getComments = function(collection, infohash, torrent) {
        var comments = HttpConnector.doGet('/collection/'+collection+'/island/'+infohash+'/info/'+torrent+'/comments/?output=json');
        return comments.evalJSON(true).data;
    }

    this.getCollections = function(collection, reload) {
        if (this.collections == null || reload) {
            this.torrentdata = HttpConnector.doGet('/collection/'+collection+'/coast/pilots/?output=json');
            this.torrentdata = this.torrentdata.evalJSON(true);
            this.collections = new Array();
            var assoc = new Object();
            for (var i=0; i<this.torrentdata.data.length; i++) {

                if (/\w*0x/.test(this.torrentdata.data[i][0])) {
                    this.pilots = this.torrentdata.data[i][1].evalJSON(true);
                    for (var i2=0; i2<this.pilots.length; i2++) {
                        if( this.pilots[i2].length == 40)
                        assoc[this.pilots[i2]] =  this.pilots[i2];
                    }
                }
            }


            for (var field in assoc) {
                collection2name = HttpConnector.doGet('/collection/'+assoc[field]+'/info/title?timeout=0')
                if (!collection2name) continue;
                this.collections.push(assoc[field]);
            }
        }

        return this.collections;
    }

    this.getPeers = function(collection,reload) {
        if (this.peers == null || reload) {
            this.peers = HttpConnector.doGet('/collection/'+collection+'/island/?output=json');
            this.peers = this.peers.evalJSON(true);
        }
        return this.peers;
    }

    this.getTags = function(infohash, torrent, collection) {
        var tags = HttpConnector.doGet('/collection/'+collection+'/island/'+infohash+'/info/'+torrent+'/tags/?output=json');
        tags = tags.evalJSON(true);
        var assoc = new Object;
        var uniqtags = 0;
        for (var i=0; i<tags.data.length; i++) {
            if (tags.data[i][1] != '' && tags.data[i][1].length < TAG_MAX_LENGTH) {
                tags.data[i][1] = tags.data[i][1].toLowerCase();
                if (assoc[tags.data[i][1]] != null) {
                    assoc[tags.data[i][1]]++;
                } else {
                    assoc[tags.data[i][1]] = 0;
                    uniqtags++;
                }
            }
        }
        var result = new Array();
        var i=0;

        while (i<uniqtags) {
            var count = null;
            var curtags = null;

            for (var key in assoc) {
                if ((count == null)||(assoc[key] > count)) {
                    curtags=new Array();
                    curtags.push(key);
                    count = assoc[key];
                } else if(assoc[key] == count) {
                    curtags.push(key);
                }
            }

            curtags = TrackerUtils.randomizeArray(curtags);

            if (count != null) {
                for (var j=0; j<curtags.length; j++) {
                    result.push(curtags[j]);
                    delete assoc[curtags[j]];
                    i++;
                }
            }
        }
        return result;
    }
    
    this.getMyTags = function(infohash, torrent, collection) {
        var tags = HttpConnector.doGet('/collection/'+collection+'/island/'+infohash+'/info/'+torrent+'/tags/?output=json');
        tags = tags.evalJSON(true);
        var result = new Array();
        var myFingerprint = Util.getFingerprint();
        for (var i=0; i<tags.data.length; i++) {
            var fingerprint = tags.data[i][0].slice(-40);
            if (fingerprint == myFingerprint) {
                if (tags.data[i][1] != '') {
                    result.push(tags.data[i][1]);
                }
            }
        }
        return result;
    }
    this.clearMyTags = function(infohash, torrent, collection) {
        var tags = HttpConnector.doGet('/collection/'+collection+'/island/'+infohash+'/info/'+torrent+'/tags/?output=json');
        tags = tags.evalJSON(true);
        var myFingerprint = Util.getFingerprint();
        for (var i=0; i<tags.data.length; i++) {
            var fingerprint = tags.data[i][0].slice(-40);
            if (fingerprint == myFingerprint) {
                var taghash = tags.data[i][0].split('/')[0];
                HttpConnector.doPost('/collection/'+collection+'/island/'+infohash+'/info/'+torrent+'/tags/'+taghash, '')
            }
        }
    }
    this.postComment = function(infohash, torrent, nick, tags, msg, collection) {
        var profile = Util.getDefaultProfile();
        if(!profile) return;
        var comment = Object.toJSON({
            published: Util.getUTCDate(),
            author: {
                profile: profile,
                name: nick
            },
            content: msg
        });

        tags = tags.replace(/\W+/g, ","); // Convert all white space & special characters to commas..
        tags = tags.split(','); // ..and split it to an array

        try {
            if (msg != '') {
                var url = '/collection/' + collection + '/island/' + infohash +
                          '/info/' + torrent +'/comments/'+ Util.getUTCDate();
                HttpConnector.doPost(url, comment);
            }
            this.clearMyTags(infohash, torrent, collection);
            for (var i=0; i<tags.length; i++) {
                tags[i] = tags[i].toLowerCase();
                var taghash = HttpConnector.doGet('/island/'+collection+'/hash?string='+tags[i]);
                var url =  '/collection/' + collection + '/island/' + infohash + '/info/'+torrent+'/tags/' + taghash;
                HttpConnector.doPost(url, tags[i]);
            }
        } catch (e) {
            alert(e);
        }
    }
};

function create_new_island(coast) {
    var html = '<?xml version="1.0" encoding="utf-8"?>\n<?xml-stylesheet href="/static/style/tracker/island.css" type="text/css"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\n "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> \n<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n    <head>\n        <script type="text/javascript" src="/static/js/prototype.js"></script>\n        <script type="text/javascript" src="/static/js/httpconnector.js"></script>\n        <script type="text/javascript" src="/static/js/tracker/tracker.js"></script>\n        <script type="text/javascript" src="/static/js/tracker/island.js"></script>\n<script type="text/javascript" src="/static/js/util.js"></script>\n        <title>P2PFusion Tracker</title>\n        <link rel="stylesheet" href="/static/style/tracker/island.css" type="text/css" title="Fusion Island" />\n    </head>     \n    <body>         \n        <div id="view"></div>\n    </body>\n</html>  \n';

    d = {}
    d['coast'] = coast
    conf = Object.toJSON(d)

    location = '/?create_collection=true'
        + '&put:info/title=' + encodeURIComponent(Util.getRealName() + "'s Island")
        + '&put:info/type=tag:hiit.fi,2007-07:island'
        + '&put:island/conf=' + encodeURIComponent(conf)
        + '&put:web/index.html=' + encodeURIComponent(html);
}

function TrackerUtils() {}
TrackerUtils.friendlyName = function(name){
    if (/^.*\.torrent$/.test(name)) {
        return name.slice(0, -8);
    }
    return name;
}

TrackerUtils.searchTag = function(collection, tag) {

    var taghash = HttpConnector.doGet('/island/'+collection+'/hash?string='+tag.toLowerCase());
    var connector = new TrackerConnector();
    var keys = connector.getTorrentinfos(collection);
    var assoc = new Object();
    for (var i=0; i<keys.length; i++) {
        if (keys[i][1] == '') continue;
        if (taghash == keys[i][0].slice(-83, -43)) {
            if (keys[i][0].match(/tags\/(\w*)\/\w*$/)[1] == taghash){
                assoc[keys[i][0].match(/(.*)\/tags/)] = keys[i];
            }
        }
    }
    var result = new Array();
    for (var key in assoc) {
        assoc[key][0] = collection+'/'+assoc[key][0];
        assoc[key][1] = assoc[key][1].toLowerCase();
        result.push(assoc[key]);
    }

    return result;
}

TrackerUtils.randomizeArray = function(array) {
    var size = array.length -1;
    var result = new Array();
    while(size >= 0) {
        var from = Math.floor(Math.random()*size);
        var last = array[size];
        array[size] = array[from];
        array[from] = last;
        var toPush = array.pop();
        result.push(toPush);
        size--;
    }
    return result;
}

TrackerUtils.bytesToMbytes = function(value) {
    if (isNaN(value)) return '-';
    if (value < 1000) return value + ' B';
    value = value / 1000;
    if (value < 1000) return value.toFixed(1) + ' KB';
    value = value / 1000;
    if (value < 1000) return value.toFixed(1) + ' MB';
    value = value / 1000;
    return value.toFixed(1) + ' GB';
}
TrackerUtils.getAuthor = function(obj) {
    try {
        return obj.author.name.escapeHTML();
    } catch(e) {
        return "";
    }
}
TrackerUtils.getAuthorProfile = function(obj) {
    try {
        return obj.author.profile.escapeHTML();
    } catch(e) {
        return "";
    }
}
TrackerUtils.getContent = function(obj) {
    try {
        return obj.content.escapeHTML();
    } catch (e) {
        return "";
    }
}

TrackerUtils.getFancyPublishDate = function(obj) {
    try {
        return Util.getUTCFriendlyDate(obj.published).escapeHTML();
    } catch (e) {
        return "";
    }
}

TrackerUtils.getNiceTags = function(tags, limit, selected) {
    var ret = "";
    for (var i=0; i<tags.length && i<limit; i++) {
        var tag = tags[i].escapeHTML()
        ret += "<a class=\"tag"
        if(tag == selected) {
            ret += " selected"
        }
        ret += "\" href=\"?page=search&query="+tag+"\">"+tag+"</a> ";
    }

    if( limit < tags.length )
    {
        ret += '<span title=" ...';
        for (var i=limit; i<tags.length; i++)
        {
            var tag = tags[i].escapeHTML();
            ret += ', '
            
            if(tag == selected) {
                ret +=  tag.toUpperCase();
            }
            else
            {
                ret += tag
            }
        }
        ret += '">...</span>';
    }

    return ret;
}

TrackerUtils.getTagCloud = function(tags, limit) {
    var ret = "<div class=\"tagcloud\">";

    for (var i=0; i<tags.length && i<limit; i++) {
        ret += "<a class=\"tag\" href=\"?page=search&query="+tags[i].escapeHTML()+"\">"+tags[i].escapeHTML()+"</a> ";
    }

    ret += "<span class=\"justifier\">&nbsp;&nbsp;</span></div>";

    if( limit < tags.length )
    {
        ret += '<div class="taghide">The ' + (tags.length - limit) + ' least frequently used tags aren\'t displayed above.</div>';
    }

    return ret;
}
